#include "Util.h"
#include "DXMgr.h"
#include "InputMgr.h"
#include "Renderer.h"
#include "D3DX9Mesh.h"

namespace Util
{
	float GetRandomFloat(float lowBound, float highBound)
	{
		if(lowBound >= highBound)
			return lowBound;
		float f = (rand() % 10000) * 0.0001f;
		return (f * (highBound - lowBound) + lowBound);
	}
	DWORD FtoDw(float a_float)
	{
		return *((DWORD*)(&(a_float)));
	}
	bool RayPick(ID3DXMesh* a_pMesh, D3DXMATRIX a_matWorld, float& a_outDist)
	{
		float tempDist = a_outDist;

		D3DXMATRIX matProj;
		D3DXMATRIX matView;

		Renderer::GetInstance().GetActiveCamera()->GetViewMatrix(matView);

		//get the world matrix of the mesh
		D3DVIEWPORT9 viewPort;
		DXMgr::GetInstance().GetDevice()->GetViewport(&viewPort);
		float width = viewPort.Width;
		float height = viewPort.Height;

		D3DXMatrixPerspectiveFovLH(&matProj, 3.14f / 4, width/height, 1, 200);

		float xpos = InputMgr::GetInstance().GetMousePos().x;
		float ypos = InputMgr::GetInstance().GetMousePos().y;

		D3DXVECTOR3 r, a;

		//Get ray origin on near frustum
		r.x = xpos;
		r.y = ypos;
		r.z = 0.0f;

		//Get ray origin on far frustum
		a.x = xpos;
		a.y = ypos;
		a.z = 1.0f;

		//Unproject into object space
		D3DXVec3Unproject(&r, &r, &viewPort, &matProj, &matView, &a_matWorld);
		D3DXVec3Unproject(&a, &a, &viewPort, &matProj, &matView, &a_matWorld);

		//Subtract the far from the near to get the direction of the ray
		a -= r;

		DWORD a_numHits;
		BOOL hit;
		D3DXIntersect(a_pMesh, &r, &a, &hit, NULL, NULL, NULL, &a_outDist, NULL, &a_numHits);
		//If it was hit
		if(hit)
		{
			if(tempDist != -1)
			{
				//If the distance passed in is less than the new hit distance, (new collision is closer), then return true, else return false, as another hit was found closer to the screen
				return tempDist < a_outDist ? false : true;
			}
			else
			{
				return true;
			}
		}
		//No collision found
		return false;
	}
	
	void OutputToDebug(const char* a_pText, ...)
	{
		char buffer[512];
		va_list ptr;
		va_start(ptr, a_pText);
		vsprintf_s(buffer, 512, a_pText, ptr);
		OutputDebugString(buffer);
	}
	bool BoxToBoxCollision(AABB a_lhs, AABB a_rhs)
	{
		D3DXVECTOR3 l_min = a_lhs.GetMin();
		l_min += a_lhs.GetPos();
		D3DXVECTOR3 l_max = a_lhs.GetMax();
		l_max += a_lhs.GetPos();

		D3DXVECTOR3 r_min = a_rhs.GetMin();
		r_min += a_rhs.GetPos();
		D3DXVECTOR3 r_max = a_rhs.GetMax();
		r_max += a_rhs.GetPos();

		//Check to see if the drawable object overlaps the node at all
		if(l_max.x > r_min.x)
		{
			if(l_min.x < r_max.x)
			{
				//Inside top wall
				if(l_max.y > r_min.y)
				{
					if(l_min.y < r_max.y)
					{		
						//Inside back wall
						if(l_max.z > r_min.z)
						{
							if(l_min.z < r_max.z)							
							{
								//If it makes it here, it is overlapping the node, return true
								return true;
							}
						}
					}
				}
			}
		}
		//No collision found
		return false;
	}
}